import * as http from 'http'
import config from '../config'
import { LoginUser, SimpleUser } from '../interfaces'
import _ from 'lodash'
import { Fetch } from './http'
import { UUID, formatString, logger } from './common'
import { deleteUser, getUser, setUser } from '../global'

export const getLoginUser = async (req?: http.IncomingMessage): Promise<LoginUser | undefined> => {
  const { method, headers_key, url, mapping, access_token } = config.server.check
  const token = _.get(req?.headers, 'access_token') as string
  const username = _.get(req?.headers, 'access_username') as string
  const key = _.get(req?.headers, headers_key) as string
  const cache = getUser(key)
  if (cache) {
    return cache
  }
  // 特殊用户准入
  if (access_token && token === access_token && username) {
    const user: LoginUser = {
      username,
      name: username,
      token: formatString(access_token),
    }
    setUser(key, user)
    return user
  }
  
  const res = await Fetch(`${config.server.base}${url}`, {
    method,
    headers: {
      [headers_key]: key
    },
    timeout: 10000,
  })

  if (res) {
    const user: LoginUser = {
      username: _.get(res, mapping.username),
      name: _.get(res, mapping.name),
      token: formatString(UUID()),
    }
    if (user.username) {
      setUser(key, user)
      return user
    }
    logger.log('Info', 'not login, req.headers: ', req.headers, ', key: ', key)
    return undefined
  }
  return res
}

export const logout = async (req?: http.IncomingMessage) => {
  const { headers_key } = config.server.check
  const key = req?.headers?.[headers_key] + ''
  deleteUser(key)
}

export const getAllUsers = async (req?: http.IncomingMessage): Promise<SimpleUser[]> => {
  const { robots } = config
  const { method, url, body, headers = {}, mapping } = config.server.users
  const res = await Fetch(`${config.server.base}${url}`, {
    method,
    headers: Object.assign({}, req?.headers, headers),
    timeout: 10000,
  }, body)

  if (res) {
    const list = _.get(res, mapping.users)
    if (!list) {
      logout(req)
      return null
    }
    const users: SimpleUser[] = list.map(item => {
      return {
        username: _.get(item, mapping['user.username']),
        name: _.get(item, mapping['user.name']),
        group: _.get(item, mapping['user.group']),
        avatar: _.get(item, mapping['user.avatar']),
      }
    })
    if (robots) {
      robots.forEach(robot => {
        users.push({
          username: robot.name,
          name: robot.name,
          avatar: robot.avatar,
        })
      })
    }
    return users
  }
}

export const getRobotResponse = async (content: string): Promise<{ name: string, result: string }[]> => {
  const robots = config.robots
  if (!robots?.length) {
    return null
  }
  const results: { name: string, result: string }[] = []
  for (let i = 0; i < robots.length; i++) {
    const robot = robots[i];
    const at = `@${robot.name}[\\s\\t\\n\\r]`
    let msg = content
    // logger.log('Info', content, new RegExp(at).test(content), robot.url.replace('${msg}', content))
    if (new RegExp(at).test(content)) {
      msg = content.replace(new RegExp(at, 'g'), '')
      let result = null
      try {
        let body = undefined
        if (robot.body) {
          body = JSON.stringify(robot.body, (k, v) => v === '${msg}' ? msg : v)
        }
        const res = await Fetch(robot.url.replace('${msg}', content), {
          method: body ? 'POST' : 'GET',
          headers: robot.headers,
          timeout: 10000,
        }, body)
        result = _.get(res, robot.mapping)
      } catch (e) {
        result = robot.error_msg
      }
      result = formatResult(result)
      results.push({ name: robot.name, result })
    }
  }
  return results
}
function formatResult(result: string): string {
  return result.replace(/\{br\}/g, function () {
    return '\n'
  })
}

